/*
 * Copyright (C) 2008 Wim Crols <twimpiex@gnx.be>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License Version 3
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

package be.gnx.event.consumer.application.ui.widget;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.log4j.spi.LoggingEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;

import ch.qos.logback.classic.spi.ILoggingEvent;

import be.gnx.event.consumer.application.event.LoggingEntriesEvents;
import be.gnx.event.consumer.receiver.EventProcessorEvents;
import be.gnx.event.consumer.receiver.model.Event;
import be.gnx.event.consumer.receiver.model.Events;
import be.gnx.event.consumer.receiver.model.EventsVector;
import be.gnx.event.consumer.receiver.model.Log4jEvent;
import be.gnx.event.consumer.receiver.model.LogbackEvent;

public class EventEntriesWidget extends ScrolledComposite implements EventProcessorEvents {

  protected static final List<LoggingEntriesEvents> loggingEntriesEventsList = new ArrayList<LoggingEntriesEvents>();

  private Events events = new EventsVector();

  private Table table;

  private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSSZ");

  public EventEntriesWidget(Composite parent, int style) {
    super(parent, style | SWT.H_SCROLL | SWT.V_SCROLL);
    setAlwaysShowScrollBars(false);
    setExpandVertical(true);
    setExpandHorizontal(true);

    table = new Table(this, SWT.SINGLE | SWT.FULL_SELECTION | SWT.VIRTUAL
        | SWT.BORDER);
    setContent(table);

    table.setLinesVisible(false);
    table.setHeaderVisible(true);

    TableColumn column;
    for (int columnIndex = 0; columnIndex < 6; columnIndex++) {
      column = new TableColumn(table, SWT.LEFT);
      switch (columnIndex) {
      case 0:
        column.setText("Time");
        break;
      case 1:
        column.setText("Thread");
        break;
      case 2:
        column.setText("Level");
        break;
      case 3:
        column.setText("Location");
        break;
      case 4:
        column.setText("NDC");
        break;
      case 5:
        column.setText("Message");
        break;
      default:
        column.setText("");
        break;
      }
      column.pack();
    }

    TableColumn[] cols = table.getColumns();
    for (int i = 0; i < cols.length; i++) {
      cols[i].setWidth(50);
    }

    table.addListener(SWT.SetData, new Listener() {
      public void handleEvent(org.eclipse.swt.widgets.Event event) {
        TableItem item = (TableItem) event.item;
        int index = table.indexOf(item);
        Event loggingEvent = events.get(events.size() - index - 1);
        item.setText(0, simpleDateFormat.format(loggingEvent.getTimeStamp()));
        item.setText(1, loggingEvent.getThreadName());
        item.setText(2, loggingEvent.getEventLevel().getDescription());
        item.setText(3, loggingEvent.getLocation().toString());
        if (loggingEvent.getNDC() != null) {
          item.setText(4, loggingEvent.getNDC());
        } else {
          item.setText(4, "");
        }
        item.setText(5, loggingEvent.getMessage().toString());
      }
    });

    table.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent selectionEvent) {
        if (selectionEvent.widget instanceof Table) {
          Table table = (Table) selectionEvent.widget;
          for (LoggingEntriesEvents loggingEntriesEvents : loggingEntriesEventsList) {
            loggingEntriesEvents.selectedLoggingEvent(events.get(events.size() - table
                .getSelectionIndex() - 1));
          }
        }
        super.widgetSelected(selectionEvent);
      }
    });

    addDisposeListener(new DisposeListener() {
      public void widgetDisposed(DisposeEvent disposeEvent) {
        EventEntriesWidget.this.widgetDisposed(disposeEvent);
      }
    });

    addControlListener(new ControlAdapter() {
      @Override
      public void controlResized(ControlEvent controlEvent) {
        EventEntriesWidget.this.controlResized(controlEvent);
        // super.controlResized(controlEvent);
      }
    });

  }

  private void widgetDisposed(DisposeEvent disposeEvent) {
    dispose();
  }

  private void controlResized(ControlEvent controlEvent) {
    resize();
  }

  @Override
  public void dispose() {
    
  }

  private void resize() {
    
  }

  public static void addLoggingEntriesEvents(LoggingEntriesEvents loggingEntriesEvents) {
    loggingEntriesEventsList.add(loggingEntriesEvents);
  }

@Override
public void eventReceived(Map<String, String> eventProperties, Object event,
		String client) {
	if (event instanceof ILoggingEvent) {
		events.add(new LogbackEvent((ILoggingEvent) event));
	} else if (event instanceof LoggingEvent) {
	    events.add(new Log4jEvent((LoggingEvent) event));
	}
    this.getDisplay().asyncExec(new Runnable() {
      public void run() {
        if (table.isDisposed()) {
          return;
        }
        table.setItemCount(events.size());
        table.clearAll();
        setMinSize(table.getSize());
      }
    });
}

}
